import flet as ft
import requests
import json
import base64
from io import BytesIO
import os
import tempfile
from datetime import datetime

# 使用相对导入
from .image_processor import download_image, share_image
from .utils import validate_image_size

def create_ui(page, config, logger):
    """
    根据SiliconFlow API文档创建图像生成UI
    """
    # 配置文件路径 - 使用用户临时目录
    config_file = os.path.join(tempfile.gettempdir(), "image_generator_config.json")
    # 模型配置文件路径
    models_config_file = os.path.join(os.path.dirname(__file__), "models_config.json")
    
    # 全局状态变量
    current_image = None
    
    # 加载模型配置
    def load_models_config():
        try:
            if os.path.exists(models_config_file):
                with open(models_config_file, 'r', encoding='utf-8') as f:
                    return json.load(f)
        except Exception as ex:
            logger.error(f"加载模型配置失败: {str(ex)}")
        # 如果加载失败，返回空配置
        return {"available_models": [], "image_size_options": {}}
    
    # 加载模型配置
    models_config = load_models_config()
    
    # 默认配置（空，API密钥只从缓存文件读取）
    default_config = {
        "api_key": ""
    }
    
    # 加载配置
    def load_config():
        try:
            if os.path.exists(config_file):
                with open(config_file, 'r', encoding='utf-8') as f:
                    return json.load(f)
        except Exception as ex:
            logger.error(f"加载配置失败: {str(ex)}")
        return default_config.copy()
    
    # 保存配置
    def save_config(config_data):
        try:
            with open(config_file, 'w', encoding='utf-8') as f:
                json.dump(config_data, f, ensure_ascii=False, indent=2)
        except Exception as ex:
            logger.error(f"保存配置失败: {str(ex)}")
    
    # 加载初始配置
    config_data = load_config()
    api_key = config_data["api_key"]
    available_models = models_config["available_models"]
    image_size_options = models_config["image_size_options"]
    
    # UI组件
    # 1. 模型选择
    model_dropdown = ft.Dropdown(
        label="选择模型",
        options=[
            ft.dropdown.Option(
                key=str(index),  # 使用索引作为唯一key
                content=ft.Row([
                    ft.Text(model["name"]),
                    ft.Container(width=8),
                    ft.Container(
                        content=ft.Text(
                            model["price"], 
                            size=12, 
                            color="white",
                            weight="bold"
                        ),
                        bgcolor="green" if model["price"] == "免费" else "orange",
                        padding=ft.Padding(left=6, right=6, top=2, bottom=2),
                        border_radius=4
                    )
                ])
            ) for index, model in enumerate(available_models)
        ],
        value=str(0),  # 使用第一个模型的索引作为默认值
        width=350,
        # 添加事件处理，根据索引显示模型名称
        on_change=lambda e: setattr(
            e.control,
            "value_display_text",
            available_models[int(e.control.value)]["name"]
        )
    )
    # 初始化显示第一个模型的名称
    model_dropdown.value_display_text = available_models[0]["name"]
    
    # 2. 图像尺寸选择
    size_dropdown = ft.Dropdown(
        label="图像尺寸",
        width=300
    )
    
    # 3. 提示词输入
    prompt_input = ft.TextField(
        label="提示词",
        multiline=True,
        min_lines=3,
        max_lines=5,
        hint_text="描述您想要生成的图像",
        expand=True,
        tooltip="点击右侧按钮可复制文本"
    )
    
    # 复制提示词按钮
    copy_prompt_button = ft.IconButton(
        icon=ft.Icons.COPY,
        on_click=lambda e: (
            page.set_clipboard(prompt_input.value),
            setattr(page, "snack_bar", ft.SnackBar(ft.Text("提示词已复制到剪贴板"))),
            setattr(page.snack_bar, "open", True)
        )
    )
    
    # 4. 负面提示词输入
    negative_prompt_input = ft.TextField(
        label="负面提示词",
        multiline=True,
        min_lines=2,
        max_lines=3,
        hint_text="描述您不想要在图像中出现的内容",
        expand=True,
        tooltip="点击右侧按钮可复制文本"
    )
    
    # 复制负面提示词按钮
    copy_negative_prompt_button = ft.IconButton(
        icon=ft.Icons.COPY,
        on_click=lambda e: (
            page.set_clipboard(negative_prompt_input.value),
            setattr(page, "snack_bar", ft.SnackBar(ft.Text("负面提示词已复制到剪贴板"))),
            setattr(page.snack_bar, "open", True)
        )
    )
    
    # 5. 其他参数控制
    # 批处理大小（仅Kolors模型）
    batch_size_input = ft.TextField(
        label="批处理大小 (1-4)",
        value="1",
        width=120,
        keyboard_type=ft.KeyboardType.NUMBER
    )
    
    # 随机种子
    seed_input = ft.TextField(
        label="随机种子",
        value="",
        hint_text="留空自动生成",
        width=180,
        keyboard_type=ft.KeyboardType.NUMBER
    )
    
    # 推理步数
    steps_input = ft.TextField(
        label="推理步数 (1-100)",
        value="20",
        width=150,
        keyboard_type=ft.KeyboardType.NUMBER
    )
    
    # Guidance Scale / CFG
    cfg_input = ft.TextField(
        label="CFG 值",
        value="7.5",
        width=120,
        keyboard_type=ft.KeyboardType.NUMBER
    )
    
    # 6. 结果显示区域
    result_image = ft.Image(
        visible=False,
        fit=ft.ImageFit.CONTAIN,
        expand=True
    )
    
    # 处理文件上传
    def handle_file_upload(e):
        nonlocal current_image
        if e.files:
            file = e.files[0]
            try:
                # 初始化上传图像列表（如果不存在）
                if not hasattr(page, 'uploaded_images'):
                    page.uploaded_images = []
                
                # 处理每个上传的文件
                # 限制最大上传图片数量为5张（根据编辑模型需求设置的合理限制）
                max_upload_images = 5
                remaining_slots = max_upload_images - len(page.uploaded_images)
                
                if remaining_slots <= 0:
                    page.snack_bar = ft.SnackBar(
                        content=ft.Text(f"最多只能上传{max_upload_images}张图片")
                    )
                    page.snack_bar.open = True
                    page.update()
                    return
                
                # 只处理剩余空间内的文件
                files_to_process = e.files[:remaining_slots]
                
                for file in files_to_process:
                    try:
                        # 读取图像文件
                        with open(file.path, "rb") as f:
                            img_data = f.read()
                        
                        # 转换为base64
                        import base64
                        img_base64 = base64.b64encode(img_data).decode('utf-8')
                        
                        # 创建图像对象
                        image_item = {
                            "id": len(page.uploaded_images) + 1,
                            "name": file.name,
                            "data": img_data,
                            "base64": img_base64
                        }
                        
                        # 添加到上传图像列表
                        page.uploaded_images.append(image_item)
                        
                        # 注意：不再将上传的图片设置到result_image
                        # 预览区域现在只用于显示生成的图片
                        
                        logger.info(f"已上传图像: {file.name}")
                    except Exception as img_ex:
                        logger.error(f"处理图像 {file.name} 时出错: {str(img_ex)}")
                        
                # 更新上传图像列表UI
                update_uploaded_images_list()
                
                # 显示成功提示
                page.snack_bar = ft.SnackBar(
                    content=ft.Text(f"已成功上传 {len(files_to_process)} 张图像")
                )
                page.snack_bar.open = True
                page.update()
                
            except Exception as e:
                logger.error(f"上传图像失败: {str(e)}")
                page.snack_bar = ft.SnackBar(
                    content=ft.Text(f"上传失败: {str(e)}")
                )
                page.snack_bar.open = True
                page.update()
    
    # 历史记录功能相关 - 使用用户临时目录
    history_file = os.path.join(tempfile.gettempdir(), "image_generation_history.json")
    history_data = []
    
    # API Key设置弹窗
    def open_api_key_dialog(e):
        # 输入框组件
        key_suffix_input = ft.TextField(
            label="",
            hint_text="输入您的API Key",
            expand=True
        )
        
        # 创建带前缀的输入行
        input_row = ft.Row([
            ft.Container(
                content=ft.Text("sk-", size=16),
                alignment=ft.alignment.center
            ),
            key_suffix_input
        ], vertical_alignment=ft.VerticalAlignment.CENTER, spacing=0)
        
        # 保存函数
        def save_key(e):
            nonlocal api_key
            # 允许保存空的API Key
            new_key = f"sk-{key_suffix_input.value.strip()}"
            config_data["api_key"] = new_key
            api_key = new_key
            save_config(config_data)
            
            # 更新Key按钮的文本颜色
            if not api_key or api_key == "sk-":
                api_key_button.style = ft.ButtonStyle(
                    color={ft.ControlState.DEFAULT: ft.Colors.RED}
                )
            else:
                api_key_button.style = ft.ButtonStyle(
                    color={ft.ControlState.DEFAULT: ft.Colors.GREEN}
                )
            
            # 正确的方式关闭对话框：设置open属性为False
            key_dialog.open = False
            page.update()
            # 使用正确的snack_bar属性方式
            page.snack_bar = ft.SnackBar(ft.Text("API Key已保存"))
            page.snack_bar.open = True
        
        # 创建弹窗，通过Container设置固定宽度
        key_dialog = ft.AlertDialog(
            title=ft.Text("Key"),
            content=ft.Container(
                content=ft.Column([
                    ft.Text("请输入您在硅基流动创建的Key"),
                    input_row
                ], spacing=10, tight=True),
                width=400
            ),
            actions=[
                ft.TextButton("保存", on_click=save_key)
            ],
            actions_alignment="end"
        )
        
        # 预填充当前Key（移除sk-前缀）
        if api_key.startswith("sk-"):
            key_suffix_input.value = api_key[3:]
        
        page.open(key_dialog)

    # 加载历史记录
    def load_history():
        nonlocal history_data
        try:
            if os.path.exists(history_file):
                with open(history_file, 'r', encoding='utf-8') as f:
                    history_data = json.load(f)
        except Exception as ex:
            logger.error(f"加载历史记录失败: {str(ex)}")
            history_data = []
    
    # 保存历史记录
    def save_history():
        try:
            with open(history_file, 'w', encoding='utf-8') as f:
                json.dump(history_data, f, ensure_ascii=False, indent=2)
        except Exception as ex:
            logger.error(f"保存历史记录失败: {str(ex)}")
    
    # 添加到历史记录
    def add_to_history(image_base64, prompt, model):
        nonlocal history_data
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        history_item = {
            "id": len(history_data) + 1,
            "timestamp": timestamp,
            "image_base64": image_base64,
            "prompt": prompt,
            "model": model
        }
        history_data.append(history_item)
        # 限制历史记录数量
        if len(history_data) > 50:
            history_data = history_data[-50:]
        save_history()
    
    # 删除历史记录项
    def delete_history_item(item_id):
        nonlocal history_data
        history_data = [item for item in history_data if item["id"] != item_id]
        save_history()
    
    # 正确初始化FilePicker
    file_picker = ft.FilePicker()
    file_picker.on_result = handle_file_upload
    page.overlay.append(file_picker)
    page.update()
    
    # 图片预览弹窗
    def show_image_preview(image_base64, item_id=None):
        preview_img = ft.Image(
            src_base64=image_base64,
            fit=ft.ImageFit.CONTAIN
        )
        
        # 下载函数
        def download_preview(e):
            filename = f"generated_image_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png"
            try:
                # 使用正确的save_file方法
                file_picker.on_result = lambda e: download_image(e, image_base64, filename)
                file_picker.save_file(dialog_title="保存图片", file_name=filename)
            except Exception as ex:
                status_message.value = f"下载失败: {str(ex)}"
                status_message.color = "red"
                page.update()
        
        # 创建操作按钮（添加关闭按钮）
        def close_preview_dialog(e):
            preview_dialog.open = False
            page.update()
        
        actions = [
            ft.TextButton("关闭", on_click=close_preview_dialog),
            ft.TextButton("下载", on_click=download_preview)
        ]
        
        # 如果是历史记录项，添加删除按钮
        if item_id is not None:
            def delete_and_close(e):
                delete_history_item(item_id)
                preview_dialog.open = False
                page.update()
            actions.insert(1, ft.TextButton("删除", on_click=delete_and_close))
        
        # 创建弹窗
        preview_dialog = ft.AlertDialog(
            title=ft.Text("图片预览"),
            content=ft.Container(
                content=preview_img,
                width=500,
                height=500,
                alignment=ft.alignment.center
            ),
            actions=actions,
            actions_alignment="end"
        )
        
        page.open(preview_dialog)
    
    # 历史记录弹窗
    def open_history_dialog(e):
        load_history()
        
        # 创建历史记录网格
        history_images = []
        for item in reversed(history_data):  # 最新的在前
            # 历史图片容器
            history_img_container = ft.Container(
                content=ft.Image(
                    src_base64=item["image_base64"],
                    fit=ft.ImageFit.COVER,
                    border_radius=8
                ),
                width=120,
                height=120,
                border_radius=8,
                bgcolor="#f0f0f0",
                padding=5,
                on_click=lambda e, img=item["image_base64"], item_id=item["id"]: show_image_preview(img, item_id),
                tooltip=f"{item['timestamp']}\n{item['prompt'][:30]}..."
            )
            history_images.append(history_img_container)
        
        # 创建网格视图
        grid = ft.GridView(
            controls=history_images,
            runs_count=4,
            max_extent=130,
            spacing=10,
            run_spacing=10,
            expand=True
        )
        
        # 创建历史记录弹窗，添加关闭按钮
        def close_history_dialog(e):
            history_dialog.open = False
            page.update()
        
        history_dialog = ft.AlertDialog(
            title=ft.Text("历史生成记录"),
            content=ft.Container(
                content=grid,
                width=600,
                height=500
            ),
            actions=[
                ft.TextButton("关闭", on_click=close_history_dialog)
            ],
            actions_alignment="end"
        )
        
        page.open(history_dialog)
    
    # 初始化加载历史记录
    load_history()
    
    # 7. 状态消息
    status_message = ft.Text(
        value="",
        color="green",
        size=14
    )
    
    # 8. 生成按钮
    generate_button = ft.ElevatedButton(
        text="生成图像",
        icon=ft.Icons.IMAGE,
        on_click=None,  # 稍后定义
        width=150
    )
    
    # 历史生成按钮
    history_button = ft.ElevatedButton(
        text="历史生成",
        icon=ft.Icons.HISTORY,
        on_click=open_history_dialog,
        width=150
    )
    
    # API Key按钮
    api_key_button = ft.ElevatedButton(
        text="Key",
        on_click=open_api_key_dialog,
        width=60,
        style=ft.ButtonStyle(
            color={ft.ControlState.DEFAULT: ft.Colors.RED}
          ) if not api_key or api_key == "sk-" else ft.ButtonStyle(
            color={ft.ControlState.DEFAULT: ft.Colors.GREEN}
          )
    )
    
    # 上传图像列表UI组件
    uploaded_images_list = ft.Column([])
    
    # 更新上传图像列表UI
    def update_uploaded_images_list():
        uploaded_images_list.controls.clear()
        
        if hasattr(page, 'uploaded_images') and page.uploaded_images:
            # 添加标题 - 将Text组件放入Container中以支持margin设置
            uploaded_images_list.controls.append(
                ft.Container(
                    content=ft.Text("已上传图像:", size=16, weight=ft.FontWeight.BOLD),
                    margin=ft.margin.only(bottom=10)
                )
            )
            
            # 创建图像网格
            grid = []
            for img_item in page.uploaded_images:
                # 图像容器 - 修改为与历史记录相同大小的1:1自适应图片
                img_container = ft.Container(
                    content=ft.Image(
                        src_base64=img_item["base64"],
                        fit=ft.ImageFit.COVER,
                        border_radius=8
                    ),
                    width=120,
                    height=120,
                    bgcolor="#f0f0f0",
                    border_radius=8,
                    padding=5,
                    margin=2,
                    # 点击选中此图像进行编辑
                    on_click=lambda e, img=img_item: select_uploaded_image(img)
                )
                
                # 删除按钮 - 在Flet中，使用right和top属性直接定位，而不是Position对象
                delete_button = ft.IconButton(
                    icon=ft.Icons.DELETE,
                    icon_size=20,
                    tooltip="删除图像",
                    on_click=lambda e, img_id=img_item["id"]: delete_uploaded_image(img_id),
                    # 悬浮在图像右上角
                    right=-5,
                    top=-5
                )
                
                # 组合图像和删除按钮
                combined = ft.Stack([
                    img_container,
                    delete_button
                ])
                
                grid.append(combined)
            
            # 添加横向滚动的图片列表 - 使用ListView并移除不支持的tight参数
            uploaded_images_list.controls.append(
                ft.Container(
                    content=ft.ListView(
                        horizontal=True,  # 设置为水平滚动
                        controls=grid,  # 直接使用grid列表作为控件，而不是嵌套在Row中
                        spacing=10  # 设置控件间距
                    ),
                    height=140,  # 调整高度以适应120x120的图片
                    margin=ft.margin.only(bottom=10)
                )
            )
    
    # 选择上传的图像
    def select_uploaded_image(img_item):
        # 设置为当前显示的图像
        result_image.src_base64 = img_item["base64"]
        result_image.visible = True
        
        # 显示提示
        page.snack_bar = ft.SnackBar(
            content=ft.Text(f"已选择图像: {img_item['name']}")
        )
        page.snack_bar.open = True
        page.update()
    
    # 删除上传的图像
    def delete_uploaded_image(img_id):
        if hasattr(page, 'uploaded_images'):
            # 找到要删除的图像
            deleted_img = None
            for i, img in enumerate(page.uploaded_images):
                if img["id"] == img_id:
                    deleted_img = img
                    del page.uploaded_images[i]
                    break
            
            if deleted_img:
                # 如果删除的是当前显示的图像，选择第一张或清空
                if result_image.src_base64 == deleted_img["base64"]:
                    if page.uploaded_images:
                        result_image.src_base64 = page.uploaded_images[0]["base64"]
                    else:
                        result_image.src_base64 = None
                        result_image.visible = False
                
                # 更新UI
                update_uploaded_images_list()
                page.snack_bar = ft.SnackBar(
                    content=ft.Text(f"已删除图像: {deleted_img['name']}")
                )
                page.snack_bar.open = True
                page.update()
    
    # 上传图像按钮
    upload_button = ft.ElevatedButton(
        text="上传图像",
        icon=ft.Icons.UPLOAD_FILE,
        on_click=lambda e: file_picker.pick_files(
            allow_multiple=True,  # 允许选择多个文件
            file_type=ft.FilePickerFileType.IMAGE
        )
    )
    
    # 注意：下载和分享功能现已整合到预览弹窗中
    
    # 更新尺寸选项和上传按钮状态
    def update_size_options(e):
        # 根据索引获取实际模型名称
        selected_model = available_models[int(model_dropdown.value)]["name"]
        size_dropdown.options.clear()
        
        # 获取模型对象
        model_obj = next((m for m in available_models if m["name"] == selected_model), None)
        
        # 更新尺寸选项
        if selected_model in image_size_options:
            size_dropdown.options = [ft.dropdown.Option(size) for size in image_size_options[selected_model]]
            size_dropdown.value = image_size_options[selected_model][0]  # 默认选择第一个尺寸
            size_dropdown.disabled = False
        else:
            size_dropdown.options = []
            size_dropdown.value = ""
            size_dropdown.disabled = True
        
        # Kolors模型特殊处理
        if selected_model == "Kwai-Kolors/Kolors":
            batch_size_input.disabled = False
            cfg_input.label = "Guidance Scale"
        else:
            batch_size_input.disabled = True
            cfg_input.label = "CFG 值"
            
        # 更新上传按钮状态 - 只有编辑类模型需要上传图像
        upload_button.disabled = "Edit" not in selected_model
        
        # 模型切换时清除图片列表和预览
        if hasattr(page, 'uploaded_images'):
            page.uploaded_images = []
            update_uploaded_images_list()
        
        # 清空预览图像
        result_image.src_base64 = None
        result_image.visible = False
            
        page.update()
    
    # 绑定模型选择变化事件
    model_dropdown.on_change = update_size_options
    
    # 初始化尺寸选项和上传按钮状态
    update_size_options(None)
    
    # 生成图像函数
    def on_generate(e):
        try:
            # 检查API Key是否为空
            if not api_key or api_key == "sk-":
                status_message.value = "请输入有效的API Key"
                status_message.color = "red"
                page.update()
                return
                
            # 验证输入
            prompt = prompt_input.value.strip()
            if not prompt:
                status_message.value = "请输入提示词"
                status_message.color = "red"
                page.update()
                return
            # 检查提示词长度，避免太短导致API错误
            if len(prompt) < 5:
                status_message.value = "提示词太短，请输入更详细的描述"
                status_message.color = "red"
                page.update()
                return
                
            # 检查是否为编辑类模型（需要输入图像）
            # 根据索引获取实际模型名称
            selected_model = available_models[int(model_dropdown.value)]["name"]
            if "Edit" in selected_model:
                if not hasattr(result_image, 'src_base64') or not result_image.src_base64:
                    status_message.value = "编辑类模型需要先上传或选择一张图像"
                    status_message.color = "red"
                    page.update()
                    return
            
            # 禁用按钮并显示状态
            generate_button.disabled = True
            status_message.value = "正在生成图像..."
            status_message.color = "blue"
            result_image.visible = False
            page.update()
            
            # 构建请求参数 - 严格按照SiliconFlow API文档要求
            selected_model = available_models[int(model_dropdown.value)]["name"]
            
            # 基础参数 - 根据API文档，model和prompt是必需的
            payload = {
                "model": selected_model,
                "prompt": prompt_input.value.strip()
            }
            
            # 处理编辑类模型的图像参数
            # 根据API文档，编辑类模型（如Qwen/Qwen-Image-Edit-2509）需要image参数
            if "Edit" in selected_model and hasattr(result_image, 'src_base64') and result_image.src_base64:
                # 确保图像格式符合API要求，需要添加data:image/png;base64,前缀
                image_base64 = result_image.src_base64
                if not image_base64.startswith("data:image/"):
                    image_base64 = f"data:image/png;base64,{image_base64}"
                payload["image"] = image_base64
                logger.info(f"为编辑模型添加图像参数: {selected_model}")
            
            # 添加negative_prompt（可选）
            if negative_prompt_input.value.strip():
                payload["negative_prompt"] = negative_prompt_input.value.strip()
            
            # 添加image_size（可选）
            # 根据API文档，某些模型支持此参数，如Kwai-Kolors/Kolors
            # 注意：Qwen/Qwen-Image-Edit-2509和Qwen/Qwen-Image-Edit不支持此参数
            if selected_model not in ["Qwen/Qwen-Image-Edit-2509", "Qwen/Qwen-Image-Edit"]:
                if selected_model in image_size_options and size_dropdown.value:
                    payload["image_size"] = size_dropdown.value
                    logger.info(f"添加图像尺寸参数: {size_dropdown.value}")
            
            # 添加batch_size（仅适用于Kwai-Kolors/Kolors）
            if selected_model == "Kwai-Kolors/Kolors":
                try:
                    batch_size = int(batch_size_input.value)
                    # 根据API文档，batch_size范围：1 <= x <= 4
                    if 1 <= batch_size <= 4:
                        payload["batch_size"] = batch_size
                        logger.info(f"添加批处理大小参数: {batch_size}")
                except ValueError:
                    logger.warning("批处理大小参数无效，将使用默认值")
            
            # 添加seed（可选）
            if seed_input.value.strip():
                try:
                    seed = int(seed_input.value)
                    # 根据API文档，seed范围：0 <= x <= 9999999999
                    if 0 <= seed <= 9999999999:
                        payload["seed"] = seed
                        logger.info(f"添加随机种子参数: {seed}")
                except ValueError:
                    logger.warning("随机种子参数无效，将使用默认值")
            
            # 添加num_inference_steps（可选）
            try:
                steps = int(steps_input.value)
                # 根据API文档，num_inference_steps范围：1 <= x <= 100
                if 1 <= steps <= 100:
                    payload["num_inference_steps"] = steps
                    logger.info(f"添加推理步数参数: {steps}")
            except ValueError:
                logger.warning("推理步数参数无效，将使用默认值")
            
            # 添加guidance_scale或cfg参数
            try:
                cfg_value = float(cfg_input.value)
                # 根据API文档，不同模型使用不同的参数名
                if selected_model == "Kwai-Kolors/Kolors" and 0 <= cfg_value <= 20:
                    # Kolors模型使用guidance_scale
                    payload["guidance_scale"] = cfg_value
                    logger.info(f"添加guidance_scale参数: {cfg_value}")
                elif "Qwen/Qwen-Image" in selected_model and 0.1 <= cfg_value <= 20:
                    # Qwen模型使用cfg
                    payload["cfg"] = cfg_value
                    logger.info(f"添加cfg参数: {cfg_value}")
            except ValueError:
                logger.warning("CFG/Guidance Scale参数无效，将使用默认值")
            
            # 特殊处理Qwen/Qwen-Image-Edit-2509模型的额外图像参数
            if selected_model == "Qwen/Qwen-Image-Edit-2509":
                # 此模型可能需要image2和image3参数（如有）
                # 这里暂时不实现，如需可在此处添加
                logger.info("使用Qwen/Qwen-Image-Edit-2509模型，支持额外图像参数")
            
            # 记录最终构建的请求参数
            logger.info(f"最终请求参数: {payload}")
            
            # 调用SiliconFlow API
            headers = {
                "Authorization": f"Bearer {api_key}",
                "Content-Type": "application/json"
            }
            
            # 确保API端点正确
            api_url = "https://api.siliconflow.cn/v1/images/generations"
            logger.info(f"调用SiliconFlow API: {payload}")
            
            response = requests.post(
                api_url,
                json=payload,
                headers=headers
            )
            
            if response.status_code == 200:
                result = response.json()
                logger.info(f"API调用成功: {result}")
                
                # 处理结果 - 根据SiliconFlow API文档格式
                if "images" in result and isinstance(result["images"], list) and result["images"]:
                    # 初始化上传图像列表（如果不存在）
                    if not hasattr(page, 'uploaded_images'):
                        page.uploaded_images = []
                    
                    # 处理API返回的所有图片（支持批处理）
                    generated_images = []
                    current_time = datetime.now().strftime('%Y%m%d_%H%M%S')
                    selected_model_name = available_models[int(model_dropdown.value)]["name"]
                    prompt_text = prompt_input.value.strip()
                    
                    for i, img_data in enumerate(result["images"]):
                        try:
                            # 按照API文档，响应中的图像应该包含url字段
                            if isinstance(img_data, dict) and "url" in img_data:
                                # 下载URL并转换为base64
                                image_url = img_data["url"]
                                logger.info(f"下载图像URL #{i+1}: {image_url}")
                                
                                # 创建新的请求会话以下载图像
                                image_response = requests.get(image_url, timeout=30)
                                if image_response.status_code == 200:
                                    import base64
                                    image_base64 = base64.b64encode(image_response.content).decode('utf-8')
                                    logger.info(f"图像 #{i+1} 下载并转换成功")
                                    
                                    # 重要：立即将base64数据保存到历史记录，而不是依赖临时URL
                                    # 因为根据SiliconFlow文档，生成的URL只有一小时有效期
                                    add_to_history(image_base64, prompt_text, selected_model_name)
                                    logger.info(f"图像 #{i+1} 已保存到历史记录")
                                    
                                    # 创建图像对象
                                    generated_img = {
                                        "id": len(page.uploaded_images) + i + 1,
                                        "name": f"generated_{current_time}_{i+1}.png",
                                        "base64": image_base64
                                    }
                                    generated_images.append(generated_img)
                                else:
                                    raise Exception(f"无法下载图像 #{i+1}: HTTP {image_response.status_code}")
                            else:
                                raise Exception(f"API返回的图像 #{i+1} 格式不符合预期: {type(img_data)}")
                        except Exception as img_ex:
                            logger.error(f"处理图像 #{i+1} 数据时出错: {str(img_ex)}")
                            # 继续处理其他图像，不中断
                    
                    # 批量添加生成的图像到上传图像列表
                    if generated_images:
                        # 将第一张图片设置为预览
                        result_image.src_base64 = generated_images[0]["base64"]
                        result_image.visible = True
                        
                        # 添加所有生成的图片到列表
                        page.uploaded_images.extend(generated_images)
                        update_uploaded_images_list()
                        
                        status_message.value = f"成功生成 {len(generated_images)} 张图像！"
                        status_message.color = "green"
                    else:
                        status_message.value = "图像生成过程中出现错误，未生成有效图像"
                        status_message.color = "red"
                        
                    # 显示生成的种子 - 根据API文档，seed应该在根级别返回
                    if "seed" in result:
                        seed_input.value = str(result["seed"])
                else:
                    status_message.value = "未返回图像数据或格式不正确"
                    status_message.color = "red"
                    logger.error(f"API返回格式问题: {result}")
            else:
                try:
                    # 尝试获取更详细的错误信息 - 严格遵循SiliconFlow API错误格式
                    error_info = None  # 初始化error_info变量
                    
                    # 首先检查响应是否为JSON格式
                    if response.headers.get("Content-Type") == "application/json":
                        error_info = response.json()
                        logger.info(f"错误响应JSON: {error_info}")
                        
                        # 根据SiliconFlow API文档，错误格式通常是：
                        # {"code": 错误码, "message": "错误消息", "data": null}
                        if isinstance(error_info, dict):
                            # 优先检查根级别的message和code字段（SiliconFlow标准格式）
                            if "message" in error_info:
                                error_message = error_info["message"]
                                error_code = error_info.get("code", "Unknown")
                                status_message.value = f"生成失败: {error_message} (错误码: {error_code})"
                                logger.error(f"SiliconFlow API错误: 代码={error_code}, 消息={error_message}")
                            # 其次检查error对象中的错误信息（兼容其他可能的格式）
                            elif "error" in error_info and isinstance(error_info["error"], dict):
                                error_message = error_info["error"].get("message", "未知错误")
                                error_type = error_info["error"].get("type", "Unknown")
                                status_message.value = f"生成失败: {error_message} (类型: {error_type})"
                                logger.error(f"API错误: 类型={error_type}, 消息={error_message}")
                            else:
                                status_message.value = f"生成失败: {str(error_info)}"
                                logger.error(f"未知错误格式: {error_info}")
                        else:
                            status_message.value = f"生成失败: {error_info}"
                    else:
                        # 非JSON响应处理
                        error_text = response.text[:200]  # 获取前200个字符
                        error_info = error_text + "..." if len(error_text) >= 200 else error_text
                        status_message.value = f"生成失败: HTTP {response.status_code} - {error_info}"
                        logger.error(f"非JSON错误响应: HTTP {response.status_code} - {error_info}")
                    
                    status_message.color = "red"
                    
                    # 对于服务器错误(5xx)，提供额外建议
                    if 500 <= response.status_code < 600:
                        page.snack_bar = ft.SnackBar(
                            content=ft.Text("服务器错误，可能是临时问题，请稍后重试或联系SiliconFlow技术支持")
                        )
                        page.snack_bar.open = True
                    # 对于认证错误(401)，提示检查API Key
                    elif response.status_code == 401:
                        page.snack_bar = ft.SnackBar(
                            content=ft.Text("认证失败，请检查您的API Key是否正确")
                        )
                        page.snack_bar.open = True
                    # 对于参数错误(400)，提示检查输入
                    elif response.status_code == 400:
                        page.snack_bar = ft.SnackBar(
                            content=ft.Text("请求参数错误，请检查输入的内容是否符合要求")
                        )
                        page.snack_bar.open = True
                except Exception as parse_error:
                    # 如果解析错误信息失败
                    status_message.value = f"生成失败: HTTP {response.status_code}"
                    status_message.color = "red"
                    logger.error(f"API调用失败: HTTP {response.status_code}, 解析错误信息失败: {str(parse_error)}")
                    logger.error(f"原始响应内容: {response.text[:300]}")  # 记录原始响应以便调试
                
        except Exception as ex:
            status_message.value = f"发生错误: {str(ex)}"
            status_message.color = "red"
            logger.error(f"生成过程出错: {str(ex)}")
        finally:
            generate_button.disabled = False
            page.update()
    
    generate_button.on_click = on_generate
    
    # 注意：下载功能已整合到预览弹窗中
    
    # 注意：已在UI布局中直接设置了按钮的on_click事件
    
    # 注意：分享功能已整合到预览弹窗中
    
    # 注意：已在UI布局中直接设置了按钮的on_click事件
    
    # 构建UI布局 - 使用ListView实现滚动，移除标题和横线
    main_content = ft.ListView(
        # 添加所有内容项
        controls=[
            # 输入区域
            ft.Container(
                content=ft.Column([
                    # 模型、尺寸选择和API Key按钮
                    ft.Row([model_dropdown, size_dropdown, api_key_button], alignment="space-between"),
                    
                    # 提示词（带复制按钮）
                    ft.Row([
                        prompt_input,
                        copy_prompt_button
                    ], vertical_alignment="start"),
                    # 负面提示词（带复制按钮）
                    ft.Row([
                        negative_prompt_input,
                        copy_negative_prompt_button
                    ], vertical_alignment="start"),
                    
                    # 参数控制
                    ft.Row([
                        batch_size_input,
                        seed_input,
                        steps_input,
                        cfg_input,
                        ft.Container(expand=True),
                        history_button,
                        generate_button,
                        upload_button
                    ], alignment="center"),
                    
                    # 状态消息
                    status_message
                ]),
                padding=10
            ),
            
            # 上传图像列表
            uploaded_images_list,
            
            # 预览图片卡片 - 200x200的1:1比例控件
            ft.Container(
                content=result_image,
                # 微透浅白背景
                bgcolor="rgba(255, 255, 255, 0.9)",
                padding=10,
                border_radius=8,
                # 固定200x200大小
                width=200,
                height=200,
                # 添加点击事件，点击时放大显示
                on_click=lambda e: show_image_preview(result_image.src_base64) if result_image.src_base64 else None,
                # 添加提示
                tooltip="点击图片放大预览",
                # 确保图片居中
                alignment=ft.alignment.center
            ),
            
            # 添加底部空间，确保内容不会被截断
            ft.Container(height=50)
        ],
        # 启用垂直滚动
        auto_scroll=False,
        # 设置ListView为可扩展
        expand=True,
        # 启用滑动指示器
        spacing=10
    )
    
    return main_content